package com.wxmit.framework.quartz.utils;


import cn.hutool.extra.spring.SpringUtil;
import com.wxmit.base.util.StringUtils;
import com.wxmit.framework.quartz.domain.SysJob;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;

/**
 * 任务执行工具
 *
 * @author ruoyi
 */
public class JobInvokeUtil {

    /**
     * 执行定时任务
     * @param sysJob
     * @throws Exception
     */
    public static void invokeMethod(SysJob sysJob) throws Exception{
        String invokeTarget = sysJob.getInvokeTarget();
        String beanName = getBeanName(invokeTarget);
        String methodName = getMethodName(invokeTarget);
        List<Object[]> methodParams = getMethodParams(invokeTarget);
        if(!isValidClassName(beanName)){
            //不是包名
            Object bean = SpringUtil.getBean(beanName);
            invokeMethod(bean, methodName, methodParams);
        }else{
            Object bean = Class.forName(beanName).newInstance();
            invokeMethod(bean, methodName, methodParams);
        }
    }

    /**
     * 调用任务方法
     * @param bean 目标对象
     * @param methodName 方法名
     * @param methodParams 方法参数
     */
    private static void invokeMethod(Object bean, String methodName, List<Object[]> methodParams)throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException,InvocationTargetException {
        if(methodParams != null && methodParams.size() > 0){
            //通过方法名和参数类型可直接获取对应方法
            Method method = bean.getClass().getDeclaredMethod(methodName, getMethodParamsType(methodParams));
            method.invoke(bean, getMethodParamsValue(methodParams));
        }else{
            Method method = bean.getClass().getDeclaredMethod(methodName);
            method.invoke(bean);
        }
    }

    /**
     * 获取参数值
     * @param methodParams
     * @return
     */
    private static Object[] getMethodParamsValue(List<Object[]> methodParams) {
        Object[] classs = new Object[methodParams.size()];
        int index = 0;
        for (Object[] os : methodParams)
        {
            classs[index] = (Object) os[0];
            index++;
        }
        return classs;
    }

    /**
     * 获取参数类型
     * @param methodParams
     * @return
     */
    private static Class<?>[] getMethodParamsType(List<Object[]> methodParams) {
        Class<?>[] classs = new Class<?>[methodParams.size()];
        int index = 0;
        for (Object[] methodParam : methodParams) {
            classs[index] = (Class<?>) methodParam[1];
            index++;
        }
        return classs;
    }

    /**
     * 检验是否为class包名
     */
    private static boolean isValidClassName(String beanName) {
        return StringUtils.count(beanName, ".") > 1;
    }



    private static List<Object[]> getMethodParams(String invokeTarget) {
        String paramStr = StringUtils.subBetween(invokeTarget, "(", ")");
        if(StringUtils.isEmpty(paramStr)){
            return null;
        }
        String[] params = paramStr.split(",");
        LinkedList<Object[]> classs = new LinkedList<>();
        //获取参数数据格式形如: { ['字符串',String.class],[1,Integer.class]...}
        for (String param : params) {
            String str = StringUtils.trimToEmpty(param);
            if(StringUtils.contains(str,"'") || StringUtils.contains(str,"\"")){
                //如果参数中出现 '' 说明是string类型的参数
                classs.add(new Object[]{StringUtils.replace(str,"'",""),String.class});
            }else if(StringUtils.equalsIgnoreCase(str, "true") || StringUtils.equalsIgnoreCase(str, "false")){
                // boolean布尔类型，等于true或者false
                classs.add(new Object[] { Boolean.valueOf(str), Boolean.class });
            }else if(StringUtils.containsIgnoreCase(str, "L")){
                // long长整形，包含L
                classs.add(new Object[] { Long.valueOf(StringUtils.replaceIgnoreCase(str, "L", "")), Long.class });
            }else if (StringUtils.containsIgnoreCase(str, "D")){
                // double类型
                classs.add(new Object[] { Double.valueOf(StringUtils.replaceIgnoreCase(str, "D", "")), Double.class });
            }else{
                // 其他为整形
                classs.add(new Object[] { Integer.valueOf(str), Integer.class });
            }
        }
        return classs;
    }

    /**
     * 获取方法名
     */
    private static String getMethodName(String invokeTarget) {
        String beanName = StringUtils.subBefore(invokeTarget, "(",false);
        return StringUtils.subAfter(beanName,".",true);
    }

    /**
     * 获取类名
     */
    private static String getBeanName(String invokeTarget) {
        String methodName = StringUtils.subBefore(invokeTarget, "(",false);
        return StringUtils.subBefore(methodName,".",true);
    }


}
